package org.example.tlias.aspect;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.example.tlias.context.BaseContext;
import org.example.tlias.mapper.OperateLogMapper;
import org.example.tlias.pojo.OperateLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Aspect
@Slf4j
@Component
public class LogRecordAspect {
    @Autowired
    private OperateLogMapper operateLogMapper;

    @Autowired
    private ObjectMapper objectMapper; // 需要确保Spring容器中有ObjectMapper Bean

    //  定义切点
    @Pointcut("@annotation(org.example.tlias.annotation.Log)")
    public void operateLogPointcut() {}

    @Around("operateLogPointcut()")
    public Object recordOperateLog(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = null;
        Throwable throwable = null;
        try {
            result = joinPoint.proceed(); // 执行目标方法
            return result;
        } catch (Throwable t) {
            throwable = t;
            throw t;
        } finally {
            long costTime = System.currentTimeMillis() - startTime;
            // 构建日志对象
            OperateLog operateLog = new OperateLog();
            // 设置操作人ID（根据实际系统获取）
            operateLog.setOperateEmpId(getCurrentEmpId());
            operateLog.setOperateTime(LocalDateTime.now());
            // 获取类名和方法名
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            operateLog.setClassName(signature.getDeclaringTypeName());
            operateLog.setMethodName(signature.getName());
            // 序列化方法参数
            operateLog.setMethodParams(serialize(joinPoint.getArgs()));
            // 处理返回值/异常信息
            if (throwable != null) {
                operateLog.setReturnValue("异常信息: " + throwable.getMessage());
            } else {
                operateLog.setReturnValue(serialize(result));
            }
            operateLog.setCostTime(costTime);
            // 插入日志（捕获异常避免影响主流程）
            try {
                operateLogMapper.insert(operateLog);
            } catch (Exception e) {
//                log.error("记录操作日志失败", e);
                e.printStackTrace();
            }
        }
    }

    // 序列化对象为JSON字符串
    private String serialize(Object obj) {
        try {
            return objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
//            log.warn("序列化失败", e);
            return "序列化失败: " + e.getMessage();
        }
    }

    // 获取当前操作人ID（示例，需根据实际系统实现）
    private Integer getCurrentEmpId() {
        // 示例代码，实际应从安全上下文中获取（如Spring Security）
        // 例如：SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        return Math.toIntExact(BaseContext.getCurrentId());
    }
}
